# coding:utf-8
from django.db import transaction
from django.db.models import Q, F
from django.db.models import Q, Sum, Subquery, OuterRef
from drf_yasg import openapi
from MSB_ERP.utils.base_views import MultipleOpenMixin, MultipleDestroyMixin, MultipleAuditMixin
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework import viewsets, status
from goods_info.models import GoodsInventoryModel
from erp_system.models import UserModel
from basic_info.models import SupplierModel
from warehouse_info.models import PurchaseStorageModel, PurchaseStorageItemModel
from warehouse_info.serializer.in_storage_serializer import InStorageItemSerializer, InStorageSerializer, \
    InStorageGetSerializer
from rest_framework.response import Response


class InStorageView(viewsets.ModelViewSet, MultipleDestroyMixin, MultipleAuditMixin):
    queryset = PurchaseStorageModel.objects.all()
    serializer_class = InStorageSerializer

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return InStorageGetSerializer
        return InStorageSerializer

    def get_queryset(self):
        if self.action == 'find':  # 过滤查询
            # 获取请求参数(在json中)：
            number_code = self.request.data.get('number_code', None)
            keyword = self.request.data.get('keyword', None)
            start_date = self.request.data.get('start_date', None)
            end_date = self.request.data.get('start_date', None)
            supplier = self.request.data.get('supplier', 0)
            operator_user = self.request.data.get('operator_user', 0)
            status = self.request.data.get('status', None)

            warehouse = self.request.data.get('warehouse', 0)
            account = self.request.data.get('account', 0)
            purchase_number_code = self.request.data.get('purchase_number_code', 0)
            query = Q()
            if keyword:
                child_query = Q()
                child_query.add(Q(item_list__name__contains=keyword), 'OR')
                child_query.add(Q(item_list__specification=keyword), 'OR')
                query.add(child_query, 'AND')
            if start_date:
                query.add(Q(invoices_date__gt=start_date), 'AND')
            if end_date:
                query.add(Q(invoices_date__lt=end_date), 'AND')

            if supplier:
                query.add(Q(supplier__id=supplier), 'AND')

            if account:
                query.add(Q(account__contains=account), 'AND')
            if number_code:
                query.add(Q(number_code__contains=number_code), 'AND')
            if operator_user:
                query.add(Q(operator_user__id=operator_user), 'AND')
            if status:
                query.add(Q(status=status), 'AND')
            if warehouse:
                query.add(Q(item_list__contains=warehouse), 'AND')
            if purchase_number_code:
                query.add(Q(purchase_number_code__contains=purchase_number_code), 'AND')
            return PurchaseStorageModel.objects.filter(query).distinct().all()  # distinct去重
        else:
            return PurchaseStorageModel.objects.all()

    params = openapi.Schema(type=openapi.TYPE_OBJECT, properties={
        'keyword': openapi.Schema(type=openapi.TYPE_STRING, description="名称的关键字或者型号"),
        'purchase_number_code': openapi.Schema(type=openapi.TYPE_STRING, description="描述订单关键字"),
        'start_date': openapi.Schema(type=openapi.TYPE_STRING, description="起始日期2020-10-01"),
        'number_code': openapi.Schema(type=openapi.TYPE_STRING, description="编号(序列号)"),
        'end_date': openapi.Schema(type=openapi.TYPE_STRING, description="结束日期2020-10-01"),
        'status': openapi.Schema(type=openapi.TYPE_STRING, description="状态0或者1,2,3.."),
        'supplier': openapi.Schema(type=openapi.TYPE_INTEGER, description="供应商的ID"),
        'operator_user': openapi.Schema(type=openapi.TYPE_INTEGER, description="操作用户的ID"),
        'warehouse': openapi.Schema(type=openapi.TYPE_INTEGER, description="仓库ID"),
        'account': openapi.Schema(type=openapi.TYPE_INTEGER, description="结算账户id"),

    })
    # 分页参数必须是query_param(看源码)
    page_param = openapi.Parameter(name='page', in_=openapi.IN_QUERY, description="页号", type=openapi.TYPE_INTEGER)
    size_param = openapi.Parameter(name='size', in_=openapi.IN_QUERY, description="每页显示数量",
                                   type=openapi.TYPE_INTEGER)

    @swagger_auto_schema(method='POST', request_body=params, manual_parameters=[page_param, size_param],
                         operation_description="采购订单的搜索过滤")
    @action(methods=['POST'], detail=False)
    def find(self, request, *args, **kwargs):
        return super(InStorageView, self).list(request=request, *args, **kwargs)

    # 定义批量审核的视图类
    body_json = openapi.Schema(type=openapi.TYPE_OBJECT, required=['ids'], properties={
        'ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_INTEGER),
                              description="选择需要审核的ID（主键）列表"),
        'user_id': openapi.Schema(type=openapi.TYPE_INTEGER, description='审核用户的ID')
        # TYPE_ARRAY是列表，items列表里的元素是整数类型
    })  # TYPE_OBJECT传参是json格式,required参数名字,properties规定每个参数的具体类型

    # action装饰器可以接收两个参数：methods:该action对应的请求方式
    # detail:声明该action是否与单一资源对应，是否是xxx/<pk>/方法名
    # True表示路径是xxx/<pk>/方法名
    # False表示路径是xxx/方法名
    @swagger_auto_schema(method='put', request_body=body_json,
                         operation_description="批量审核")  # 在接口注释,request_body传参,适用于接口文档，在文档中添加multiple_delete
    @action(methods=['put'], detail=False)
    @transaction.atomic  # 自动数据库事务
    def multiple_audit(self, request, *args, **kwargs):
        audit_ids = request.data.get('ids')
        user_id = request.data.get('user_id')  # 用户id
        is_audit = '1'
        # 所有需要批量审批的入库单列表
        in_list = self.get_queryset().filter(id__in=audit_ids).all()
        # 审批的用户
        check_user = UserModel.objects.get(id=int(user_id))

        # 审批的条件判断:1，入库单的状态是0,2：是否关联了采购单
        for in_storage in in_list:
            if in_storage.status != '0':  # ’0‘以后的状态是不能审批的
                return Response(data={'detail': '不能审批，订单已生效'}, status=status.HTTP_400_BAD_REQUEST)

            if in_storage.purchase:
                if in_storage.purchase.status != '1' and in_storage.purchase.status != '2' and in_storage.purchase.status != '5':
                    return Response(data={'detail': '不能审批，订单已生效'}, status=status.HTTP_400_BAD_REQUEST)

            # 处理业务逻辑
            if in_storage.supplier and in_storage.this_debt > 0:
                # 修改供应商的末期应付+=本次欠款,F是拿到原有字段的值
                SupplierModel.objects.filter(id=in_storage.supplier_id).update(
                    current_pay=F('current_pay') + in_storage.this_debt)

            if in_storage.purchase:
                # 修改关联的采购单，状态为部分入库或者全部入库，
                # 查询该采购单已经入库的数量,物品可能有多次入库，查询多个物品入库单，把入库的数量加起来，判断是部分入库还是全部入库
                in_count = PurchaseStorageModel.objects.filter(purchase_id=in_storage.purchase_id).exclude(
                    status='0').aggregate(sum=Sum('number_count'))
                if not in_count.get('sum', 0):
                    in_count = 0
                    # 之前入库的数量+当前入库数量==采购总数量
                in_counts=in_count['sum'] if in_count['sum'] else 0
                if (in_counts + in_storage.number_count) == in_storage.purchase.number_count:
                    in_storage.purchase.status = '3'  # 更改为全部入库
                else:
                    in_storage.purchase.status = '2'  # 更改为部分入库
                in_storage.purchase.save()
            # 相关货品的库存：需要增加：原来的库存+=当前入库数量
            for item in in_storage.item_list.all():
                GoodsInventoryModel.objects.filter(goods_id=item.goods_id, warehouse_id=item.warehouse_id).update(
                    cur_inventory=F('cur_inventory') + item.purchase_count)
        # 审核
        self.get_queryset().filter(id__in=audit_ids).update(status=is_audit, check_user_id=check_user,
                                                            check_user_name=check_user.real_name)

        return Response(status=status.HTTP_200_OK)
